metafile <- './quickdraw classification.csv'
meta <- read_csv(metafile, skip = 1)
Parsed with column specification:
cols(
  name = col_character(),
  animal = col_logical(),
  food = col_logical(),
  fruit = col_logical(),
  veggie = col_logical(),
  building = col_logical(),
  vechicle = col_logical(),
  bug = col_logical(),
  bird = col_logical(),
  plant = col_logical()
)
name_parts <- str_split_fixed(meta$name, coll("."), 2)
meta$basename <- name_parts[, 1]
bugs <- meta %>% filter(bug == TRUE)
Warning message:
In scan(file = file, what = what, sep = sep, quote = quote, dec = dec,  :
  EOF within quoted string
filename <- 'data/dog.stats.csv'
dogs_org <- read_csv(filename)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
filename <- 'data/cat.stats.csv'
cats_org <- read_csv(filename)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)

Clean Data

prepare_data <- function (data) {
  new_data <- data %>% mutate(drawing_time_seconds = drawing_time / 1000, drawing_time_draw_seconds = drawing_time_draw / 1000, drawing_time_pause_seconds = drawing_time_pause / 1000)
  
  new_data <- new_data %>% 
    # a few have time values not in incremental
    filter(stroke_in_order == 0) %>% 
    # a few have weird times
    filter(drawing_time_min >= 0) %>% 
    filter(drawing_time_max > 0) %>%
    filter(drawing_time_draw > 100)
  return(new_data)
}
dogs <- prepare_data(dogs_org)
cats <- prepare_data(cats_org)

dogs %>% filter(recognized == 'True') %>%  filter(drawing_time_seconds < 25) %>%  #filter(stroke_count < 4) %>%
  ggplot(aes(x = drawing_time_seconds, y = (..count..)/sum(..count..))) +
  geom_histogram(binwidth = 0.1, fill = "#607d8b") +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(limits = c(0,20)) +
  labs(title = "Dog Total Drawing Time", y = "", x = "") +
  theme_joy()
ggsave("dog_total.png", width = 6, height = 5)

rr dogs_cats <- rbind(dogs, cats)

rr dogs_cats %>% filter(drawing_time_draw_seconds <= 20) %>% ggplot(aes(x = drawing_time_draw_seconds, y = word))+ geom_joy(scale = 4) + theme_joy() + scale_y_discrete(expand = c(0.01, 0)) + scale_x_continuous(expand = c(0, 0))

rr dogs_cats_rec_sum <- dogs_cats %>% group_by(word, recognized) %>% summarise(count = n()) %>% mutate(freq = count / sum(count))

rr cats_rec <- cats %>% filter(recognized == ‘True’) dogs_rec <- dogs %>% filter(recognized == ‘True’)

rr dogs_cats_rec <- rbind(dogs_rec, cats_rec)

rr dogs_cats_rec %>% ggplot(aes(x = word, y = drawing_time_pause_seconds)) + geom_boxplot()

rr summary(dogs_rec$drawing_time_pause_seconds)

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   1.845   3.154   3.418   4.705 133.600 

rr summary(cats_rec$drawing_time_pause_seconds)

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   2.561   3.699   4.118   5.291 261.400 

rr

#dogs_cats <- rbind(cat_drawings_rec, dog_drawings_rec)

rr NA

rr dogs_cats %>% filter(drawing_time_seconds > 20) %>% count() r dogs_cats %>% filter(drawing_time_seconds > 20) %>% count() / nrow(dogs_cats)

rr summary(dogs_rec$drawing_time_seconds)

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.107   8.097  10.460  10.830  13.200 143.900 

rr summary(cats_rec$drawing_time_seconds)

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.114   6.744   8.963   9.593  12.120 267.000 

rr dogs_cats %>% filter(drawing_time_seconds > 20) %>% ggplot(aes(x = word, y = drawing_time_pause_seconds)) + geom_boxplot()

rr NA

rr pg

$data
$data[[1]]

$data[[2]]


$layout
<ggproto object: Class Layout>
    facet: <ggproto object: Class FacetNull, Facet>
        compute_layout: function
        draw_back: function
        draw_front: function
        draw_labels: function
        draw_panels: function
        finish_data: function
        init_scales: function
        map: function
        map_data: function
        params: list
        render_back: function
        render_front: function
        render_panels: function
        setup_data: function
        setup_params: function
        shrink: TRUE
        train: function
        train_positions: function
        train_scales: function
        vars: function
        super:  <ggproto object: Class FacetNull, Facet>
    finish_data: function
    get_scales: function
    map: function
    map_position: function
    panel_layout: data.frame
    panel_ranges: list
    panel_scales: list
    render: function
    render_labels: function
    reset_scales: function
    setup: function
    train_position: function
    train_ranges: function
    xlabel: function
    ylabel: function
    super:  <ggproto object: Class Layout>

$plot

rr dogs_rec <- dogs_rec %>% mutate(time_bin = floor(drawing_time_draw_seconds)) dog_bins <- dogs_rec %>% group_by(time_bin) %>% summarise(count = n()) %>% mutate( freq = count / sum(count))

rr cats_rec <- cats_rec %>% mutate(time_bin = floor(drawing_time_draw_seconds)) cat_bins <- cats_rec %>% group_by(time_bin) %>% summarise(count = n()) %>% mutate( freq = count / sum(count))

rr dog_bins %>% ggplot() + geom_bar(data = dog_bins, mapping = aes(x = time_bin, y = freq), stat=‘identity’, fill = ‘blue’, alpha = 0.6) + geom_bar(data = cat_bins, mapping = aes(x = time_bin, y = freq), stat=‘identity’, fill = ‘red’, alpha = 0.6) + scale_x_continuous(limits=c(0, 25))

Sample Data

Test if the different n sizes affecting data.

rr cats_rec_sample <- cats_rec %>% sample_n(50000) dogs_rec_sample <- dogs_rec %>% sample_n(50000)

Pause Time

rr mean(cats_rec$drawing_time_seconds)

[1] 9.593239

rr mean(dogs_rec$drawing_time_seconds)

[1] 10.82946

rr mean(cats_rec$drawing_time_draw_seconds)

[1] 5.474867

rr mean(dogs_rec$drawing_time_draw_seconds)

[1] 7.411101

rr mean(cats_rec$stroke_count)

[1] 9.522221

rr mean(dogs_rec$stroke_count)

[1] 7.030852

rr dogs_rec %>% filter(drawing_time_draw_seconds < 30) %>% ggplot(aes(x = drawing_time_draw_seconds, y = stroke_count)) + geom_point(alpha = 1 / 100)

rr NA

rr cats_rec %>% ggplot(aes(x = drawing_time_draw_seconds, y = stroke_count)) + geom_point(alpha = 1 / 10)

rr NA

rr cats_rec %>% filter(drawing_time_pause_seconds < 20) %>% ggplot(aes(x = drawing_time_pause_seconds, y = stroke_count)) + geom_point(alpha = 1 / 10) + geom_smooth(method=‘lm’)

rr cats_rec_filtered <- cats_rec %>% filter(drawing_time_pause_seconds < 20)

rr fit <- lm(drawing_time_pause_seconds ~ stroke_count , data = cats_rec_filtered) summary(fit)


Call:
lm(formula = drawing_time_pause_seconds ~ stroke_count, data = cats_rec_filtered)

Residuals:
     Min       1Q   Median       3Q      Max 
-18.5908  -1.0138  -0.2461   0.8020  13.8677 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.301497   0.014292   21.09   <2e-16 ***
stroke_count 0.400271   0.001411  283.67   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.563 on 102933 degrees of freedom
Multiple R-squared:  0.4388,    Adjusted R-squared:  0.4387 
F-statistic: 8.047e+04 on 1 and 102933 DF,  p-value: < 2.2e-16

rr countrycodes_dogs <- dogs_rec %>% group_by(countrycode) %>% summarise(country_count = n()) %>% arrange(-country_count) countrycodes_cats <- cats_rec %>% group_by(countrycode) %>% summarise(country_count = n()) %>% arrange(-country_count)

rr top_countrycodes <- countrycodes_dogs %>% head(n = 30)

rr dogs_rec_top_countries %>% filter(drawing_time_draw_seconds < 30) %>% ggplot(aes(x = drawing_time_draw_seconds)) + facet_wrap(~ countrycode) + geom_histogram(aes(y=(..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]), binwidth = 1)

rr dogs_rec_top_countries %>% filter(drawing_time_draw_seconds < 30) %>% ggplot(aes(x = drawing_time_draw_seconds)) + facet_wrap(~ countrycode) + geom_histogram(aes(y=(..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]), binwidth = 1)

rr NA

rr dogs_rec_top_countries %>% filter(drawing_time_pause_seconds < 15) %>% ggplot(aes(x = drawing_time_pause_seconds)) + facet_wrap(~ countrycode) + geom_histogram(aes(y=(..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]), binwidth = 1)

rr NA

Category sub-sections

read_names <- function (names) {
  data_path <- './data/'
  all_cates <- vector("list", nrow(names))  
  
  for(i in 1:nrow(names)) {
    name_file <- names[i, "basename"]
    full_path <- paste(data_path, name_file, ".stats.csv", sep='')
    name <- read_csv(full_path)
    all_cates[[i]] <- name
  }
  
  all_cates_df <- do.call("rbind", all_cates)
  
  all_cates_df_clean <- prepare_data(all_cates_df)

  all_cates_df_clean_rec <- all_cates_df_clean %>% filter(recognized == 'True')
  
  return(all_cates_df_clean_rec)
  
}
all_bugs_df <- read_names(bugs)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
Parsed with column specification:
cols(
  key_id = col_double(),
  recognized = col_character(),
  word = col_character(),
  stroke_count = col_integer(),
  countrycode = col_character(),
  drawing_time = col_integer(),
  drawing_time_pause = col_integer(),
  drawing_time_draw = col_integer(),
  stroke_in_order = col_integer(),
  drawing_time_min = col_integer(),
  drawing_time_max = col_integer()
)
bugs_agg <- all_bugs_df %>% group_by(word) %>% summarise(count = n(),
            stroke_count_mean = mean(stroke_count),
            stroke_count_med = median(stroke_count),
            drawing_time_pause_sec_mean = mean(drawing_time_pause_seconds), 
            drawing_time_pause_sec_med = median(drawing_time_pause_seconds), 
            drawing_time_draw_sec_mean = mean(drawing_time_draw_seconds), 
            drawing_time_draw_sec_med = median(drawing_time_draw_seconds)) %>%
  arrange(-drawing_time_draw_sec_mean)
all_bugs_df %>% 
ggplot(aes(x = drawing_time_draw_seconds, y = factor(word, levels = bugs_agg$word), fill = factor(word, levels = bugs_agg$word))) +
geom_joy(size = 0.55 ) +
  theme_joy() +
  scale_x_continuous(limits=c(1, 20), expand = c(0.01, 0)) +
  scale_y_discrete(expand = c(0.01, 0)) + 
  scale_fill_brewer(guide = FALSE, palette = "Greys", direction = -1) + 
  labs(title = 'Bugs', x = '', y = '')

ggsave('bugs.png', width = 8, height = 12)
fruits <- meta %>% filter(fruit == TRUE)
all_fruits <- read_names(fruits)

|=========                                                                      |  11%           
|=========                                                                      |  12%           
|==========                                                                     |  12%           
|==========                                                                     |  13%    1 MB
|===========                                                                    |  14%    1 MB
|===========                                                                    |  14%    1 MB
|============                                                                   |  15%    1 MB
|=============                                                                  |  16%    1 MB
|=============                                                                  |  17%    1 MB
|==============                                                                 |  17%    1 MB
|==============                                                                 |  18%    1 MB
|===============                                                                |  19%    1 MB
|===============                                                                |  19%    1 MB
|================                                                               |  20%    1 MB
|=================                                                              |  21%    1 MB
|=================                                                              |  22%    1 MB
|==================                                                             |  22%    1 MB
|==================                                                             |  23%    1 MB
|===================                                                            |  24%    1 MB
|===================                                                            |  24%    1 MB
|====================                                                           |  25%    1 MB
|=====================                                                          |  26%    1 MB
|=====================                                                          |  27%    2 MB
|======================                                                         |  27%    2 MB
|======================                                                         |  28%    2 MB
|=======================                                                        |  29%    2 MB
|=======================                                                        |  29%    2 MB
|========================                                                       |  30%    2 MB
|=========================                                                      |  31%    2 MB
|=========================                                                      |  31%    2 MB
|==========================                                                     |  32%    2 MB
|==========================                                                     |  33%    2 MB
|===========================                                                    |  34%    2 MB
|===========================                                                    |  34%    2 MB
|============================                                                   |  35%    2 MB
|=============================                                                  |  36%    2 MB
|=============================                                                  |  36%    2 MB
|==============================                                                 |  37%    2 MB
|==============================                                                 |  38%    2 MB
|===============================                                                |  39%    2 MB
|===============================                                                |  39%    3 MB
|================================                                               |  40%    3 MB
|================================                                               |  41%    3 MB
|=================================                                              |  41%    3 MB
|==================================                                             |  42%    3 MB
|==================================                                             |  43%    3 MB
|===================================                                            |  44%    3 MB
|===================================                                            |  44%    3 MB
|====================================                                           |  45%    3 MB
|====================================                                           |  46%    3 MB
|=====================================                                          |  46%    3 MB
|======================================                                         |  47%    3 MB
|======================================                                         |  48%    3 MB
|=======================================                                        |  49%    3 MB
|=======================================                                        |  49%    3 MB
|========================================                                       |  50%    3 MB
|========================================                                       |  51%    3 MB
|=========================================                                      |  51%    3 MB
|==========================================                                     |  52%    3 MB
|==========================================                                     |  53%    4 MB
|===========================================                                    |  54%    4 MB
|===========================================                                    |  54%    4 MB
|============================================                                   |  55%    4 MB
|============================================                                   |  56%    4 MB
|=============================================                                  |  56%    4 MB
|==============================================                                 |  57%    4 MB
|==============================================                                 |  58%    4 MB
|===============================================                                |  58%    4 MB
|===============================================                                |  59%    4 MB
|================================================                               |  60%    4 MB
|================================================                               |  61%    4 MB
|=================================================                              |  61%    4 MB
|==================================================                             |  62%    4 MB
|==================================================                             |  63%    4 MB
|===================================================                            |  63%    4 MB
|===================================================                            |  64%    4 MB
|====================================================                           |  65%    4 MB
|====================================================                           |  66%    4 MB
|=====================================================                          |  66%    5 MB
|======================================================                         |  67%    5 MB
|======================================================                         |  68%    5 MB
|=======================================================                        |  68%    5 MB
|=======================================================                        |  69%    5 MB
|========================================================                       |  70%    5 MB
|========================================================                       |  71%    5 MB
|=========================================================                      |  71%    5 MB
|==========================================================                     |  72%    5 MB
|==========================================================                     |  73%    5 MB
|===========================================================                    |  73%    5 MB
|===========================================================                    |  74%    5 MB
|============================================================                   |  75%    5 MB
|============================================================                   |  76%    5 MB
|=============================================================                  |  76%    5 MB
|=============================================================                  |  77%    5 MB
|==============================================================                 |  78%    5 MB
|===============================================================                |  78%    5 MB
|===============================================================                |  79%    6 MB
|================================================================               |  80%    6 MB
|================================================================               |  81%    6 MB
|=================================================================              |  81%    6 MB
|=================================================================              |  82%    6 MB
|==================================================================             |  83%    6 MB
|===================================================================            |  83%    6 MB
|===================================================================            |  84%    6 MB
|====================================================================           |  85%    6 MB
|====================================================================           |  86%    6 MB
|=====================================================================          |  86%    6 MB
|=====================================================================          |  87%    6 MB
|======================================================================         |  88%    6 MB
|=======================================================================        |  88%    6 MB
|=======================================================================        |  89%    6 MB
|========================================================================       |  90%    6 MB
|========================================================================       |  90%    6 MB
|=========================================================================      |  91%    6 MB
|=========================================================================      |  92%    6 MB
|==========================================================================     |  93%    7 MB
|===========================================================================    |  93%    7 MB
|===========================================================================    |  94%    7 MB
|============================================================================   |  95%    7 MB
|============================================================================   |  95%    7 MB
|=============================================================================  |  96%    7 MB
|=============================================================================  |  97%    7 MB
|============================================================================== |  98%    7 MB
|===============================================================================|  98%    7 MB
|===============================================================================|  99%    7 MB
|================================================================================| 100%    7 MB
fruits_agg <- all_fruits %>% group_by(word) %>% summarise(count = n(),
            stroke_count_mean = mean(stroke_count),
            stroke_count_med = median(stroke_count),
            drawing_time_pause_sec_mean = mean(drawing_time_pause_seconds), 
            drawing_time_pause_sec_med = median(drawing_time_pause_seconds), 
            drawing_time_draw_sec_mean = mean(drawing_time_draw_seconds), 
            drawing_time_draw_sec_med = median(drawing_time_draw_seconds)) %>%
  arrange(-drawing_time_draw_sec_mean)
all_fruits %>% 
ggplot(aes(x = drawing_time_draw_seconds, y = factor(word, levels = fruits_agg$word), fill = factor(word, levels = fruits_agg$word))) +
geom_joy(size = 0.55 ) +
  theme_joy() +
  scale_x_continuous(limits=c(1, 20), expand = c(0.01, 0)) +
  scale_y_discrete(expand = c(0.01, 0)) + 
  scale_fill_brewer(guide = FALSE, palette = "Oranges", direction = -1) + 
  labs(title = 'Fruits', x = '', y = '')

ggsave('fruits.png', width = 8, height = 12)
all_fruits %>% filter(word == "banana") %>%
  ggplot(aes(x = drawing_time_seconds,  y = (..count..)/sum(..count..))) +
  geom_histogram(binwidth = 0.1, fill = "#FFD600") + 
  scale_x_continuous(limits = c(0, 20)) + 
  scale_y_continuous(labels = scales::percent) +
  theme_joy()  + 
  labs(title = "Banana Total Drawing Time", x = "", y = "")
ggsave("banana_total.png", width = 6, height = 5)

all_fruits %>% filter(word == "banana") %>%
  ggplot(aes(x = drawing_time)) +
  geom_histogram(binwidth = 100) +
  scale_x_continuous(limits = c(0, 20000))

all_fruits %>% filter(word == "banana") %>%
  ggplot(aes(x = stroke_count)) +
  geom_histogram(binwidth = 1) 

  #scale_x_continuous(limits = c(0, 20))
all_fruits %>% filter(stroke_count < 5) %>%
  ggplot(aes(x = drawing_time)) +
  geom_histogram(binwidth = 100) +
  scale_x_continuous(limits = c(0, 20000))

all_cates %>% #filter(stroke_count < 5) %>%
  ggplot(aes(x = drawing_time_seconds,  y = (..count..)/sum(..count..))) +
  geom_histogram(binwidth = 1) +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(limits = c(0, 10)) + 
  theme_joy() +
  labs(title = "All Categories Total Drawing Time (binwidth = 1)", y = '', x = '')
ggsave('all_total_1.png', width = 6, height = 5)

bananas %>% filter(recognized == 'True') %>%
  ggplot(aes(x = drawing_time_draw_seconds )) +
  geom_histogram(binwidth = 0.1) +
  scale_x_continuous(limits = c(0.5, 8))

ggplot() +
  geom_histogram(data = bananas, aes(x = drawing_time_seconds, y = (..count..)/sum(..count..)), alpha = 1.0, fill = "#FFD600", binwidth = 0.1) +
  geom_histogram(data = all_fruits %>% filter(stroke_count < 5), aes(x = drawing_time_seconds, y = (..count..)/sum(..count..)), alpha = 0.6, fill = 'black', binwidth = 0.1) +
  #geom_histogram(data = dogs, aes(x = drawing_time_seconds, y = (..count..)/sum(..count..)), alpha = 0.6, fill = 'blue', binwidth = 0.1) +
  scale_x_continuous(limits = c(0, 10), breaks = seq(0,10,0.5)) + 
  scale_y_continuous(labels = scales::percent) +
  labs(title = "Banana vs All Fruit Drawing Time (binwidth = 0.1)", y = "", x = "Drawing Time (secs)") +
  theme_light()
ggsave("bananas_vs_fruit.png", width = 6, height = 5) 

mean(all_fruits$drawing_time_seconds)
[1] 6.211525
mean(dogs$drawing_time_seconds)
[1] 11.08655
getmode <- function(v) {
   uniqv <- unique(v)
   uniqv[which.max(tabulate(match(v, uniqv)))]
}
getmode(bananas$drawing_time_seconds)
[1] 2.615
summary()
bananas_two_sec %>%
  ggplot(aes(x =  factor(stroke_count))) +
  geom_bar()

bananas %>% filter(stroke_count < 4) %>%
  ggplot(aes(x = drawing_time_seconds)) +
  geom_histogram(binwidth = 0.5) +
  scale_x_continuous(limits = c(1, 8)) + 
  facet_wrap(~ stroke_count)

pears %>% filter(stroke_count < 6) %>%
  ggplot(aes(x = drawing_time_seconds)) +
  geom_histogram(binwidth = 0.5) +
  scale_x_continuous(limits = c(0, 10)) + 
  facet_wrap(~ stroke_count)

dogs %>% filter(stroke_count < 4) %>% filter(drawing_time_seconds < 20) %>% filter(recognized == 'True')  %>%
  ggplot(aes(x = drawing_time_seconds)) +
  geom_histogram(binwidth = 0.1) +
  scale_x_continuous(limits = c(4, 11)) +
  facet_wrap(~ stroke_count)

dogs_m <- dogs %>% mutate(sec = floor(drawing_time_seconds), time_in_sec = drawing_time_seconds - sec)
dogs_m %>% filter(stroke_count < 4) %>% filter(sec %in% c(4,5,6,7,8,9, 10, 11, 12, 13, 14, 15)) %>%
  ggplot(aes(x = time_in_sec)) +
  geom_histogram(binwidth = 0.01) +
  #scale_x_continuous(limits = c(1, 20)) +
  facet_wrap(~ sec)

dogs %>% filter(stroke_count < 4) %>% filter(drawing_time_seconds < 20) %>%
  ggplot(aes(x = drawing_time_seconds)) +
  geom_area()
Error in eval(expr, envir, enclos) : object 'y' not found

bananas_by_time <- bananas %>% group_by(round_time, stroke_count) %>% summarise(n = n()) %>% mutate(freq = n / sum(n))
bananas_by_time %>% filter(round_time < 20) %>% filter(stroke_count < 10) %>%
  ggplot(aes(x = round_time, fill = factor(stroke_count), y = freq)) +
  geom_bar(stat = 'identity')
animals_meta <- meta %>% filter(animal == TRUE)
all_animals <- read_names(animals_meta)

library(RColorBrewer)
animals_agg <- all_animals %>% group_by(word) %>% summarise(count = n(),
            stroke_count_mean = mean(stroke_count),
            stroke_count_med = median(stroke_count),
            drawing_time_pause_sec_mean = mean(drawing_time_pause_seconds), 
            drawing_time_pause_sec_med = median(drawing_time_pause_seconds), 
            drawing_time_draw_sec_mean = mean(drawing_time_draw_seconds), 
            drawing_time_draw_sec_med = median(drawing_time_draw_seconds)) %>%
  arrange(-drawing_time_draw_sec_mean)
all_animals %>% 
ggplot(aes(x = drawing_time_draw_seconds, y = factor(word, levels = animals_agg$word), fill = factor(word, levels = animals_agg$word))) +
geom_joy(size = 0.55 ) +
  theme_joy() +
  scale_x_continuous(limits=c(1, 18), expand = c(0.01, 0)) +
  scale_y_discrete(expand = c(0.01, 0)) + 
  #scale_fill_brewer(guide = FALSE, palette = "YlGnBu", direction = -1) + 
  scale_fill_manual(values=rep(brewer.pal(6,"GnBu"),times=9), guide = FALSE) +
  labs(title = 'Animals', x = '', y = '')
ggsave('animals.png', width = 8, height = 12)
all_cates <- read_names(meta)
all_agg <- all_cates %>% group_by(word) %>% summarise(n = n(),
            scount_me = mean(stroke_count),
            scount_md = median(stroke_count),
            d_pause_me = mean(drawing_time_pause_seconds), 
            d_pause_md = median(drawing_time_pause_seconds), 
            d_draw_me = mean(drawing_time_draw_seconds), 
            d_draw_md = median(drawing_time_draw_seconds),
            d_total_md = median(drawing_time_seconds),
            d_total_me = mean(drawing_time_seconds)) %>%
  arrange(-d_draw_me)
all_agg_rec <- all_cates %>% filter(recognized == 'True') %>% group_by(word) %>% summarise(n = n(),
            scount_me = mean(stroke_count),
            scount_md = median(stroke_count),
            d_pause_me = mean(drawing_time_pause_seconds), 
            d_pause_md = median(drawing_time_pause_seconds), 
            d_draw_me = mean(drawing_time_draw_seconds), 
            d_draw_md = median(drawing_time_draw_seconds),
            d_total_md = median(drawing_time_seconds),
            d_total_me = mean(drawing_time_seconds)) %>%
  arrange(-d_draw_me)
all_agg %>%
  ggplot(aes(x = drawing_time_draw_sec_mean, y = drawing_time_draw_sec_med)) +
  geom_point()
library(ggbeeswarm)
all_agg %>% 
  ggplot(aes(x = drawing_time_draw_sec_med, y = '')) + 
  geom_beeswarm(groupOnX = FALSE, cex=2.8, size = 2) +
  labs(x = '', y = '')
  #geom_quasirandom(groupOnX = FALSE, varwidth = TRUE)
  
write_csv(all_agg, 'all_aggregates.csv')

All Categories

data_path <- './data/'
stat_files <- list.files(path = data_path, pattern = '\\.stats\\.csv')
length(stat_files)
all_cates <- vector("list",length(stat_files))
length(all_cates)
for(i in 1:length(stat_files)) {
  stat_file <- stat_files[i]
  full_path <- paste(data_path, stat_file, sep='')
  print(full_path)
  cate_org <- read_csv(full_path)
  cate <- prepare_data(cate_org)
  all_cates[[i]] <- cate
  
}
all_cates_df <- do.call("rbind", all_cates)
all_cates_df_clean <- prepare_data(all_cates_df)
all_cates_df_clean_rec <- all_cates_df_clean %>% filter(recognized == 'True')
all_cates_mean <- all_cates_df_clean_rec %>% group_by(word) %>% 
  summarise(count = n(),
            stroke_count_mean = mean(stroke_count),
            stroke_count_med = median(stroke_count),
            drawing_time_pause_sec_mean = mean(drawing_time_pause_seconds), 
            drawing_time_pause_sec_med = median(drawing_time_pause_seconds), 
            drawing_time_draw_sec_mean = mean(drawing_time_draw_seconds), 
            drawing_time_draw_sec_med = median(drawing_time_draw_seconds)) %>%
  arrange(-drawing_time_draw_sec_mean)

all_cates_df_clean_rec$word <- factor(all_cates_df_clean_rec$word, levels = all_cates_df_clean_rec$word[order(all_cates_df_clean_rec$word)])


all_cates_df_clean_rec %>% filter(drawing_time_draw_seconds <= 20) %>%
  ggplot(aes(x = drawing_time_draw_seconds, y = word ))+
  geom_joy(scale = 4) + theme_joy()
all_cates_df %>% filter(word == 'dog') %>% count()
all_cates_df_clean_rec %>% filter(word == 'dog') %>% filter(drawing_time_draw_seconds <= 20) %>%
 ggplot(aes(x = drawing_time_draw_seconds)) +
  geom_histogram(binwidth = 1) + 
  labs(title = "Histogram of Drawing Time")
LS0tCnRpdGxlOiAiUXVpY2tEcmF3IFRpbWUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnam95KQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoZm9yY2F0cykKYGBgCgpgYGB7cn0KbWV0YWZpbGUgPC0gJy4vcXVpY2tkcmF3IGNsYXNzaWZpY2F0aW9uLmNzdicKbWV0YSA8LSByZWFkX2NzdihtZXRhZmlsZSwgc2tpcCA9IDEpCm5hbWVfcGFydHMgPC0gc3RyX3NwbGl0X2ZpeGVkKG1ldGEkbmFtZSwgY29sbCgiLiIpLCAyKQptZXRhJGJhc2VuYW1lIDwtIG5hbWVfcGFydHNbLCAxXQpgYGAKCmBgYHtyfQpidWdzIDwtIG1ldGEgJT4lIGZpbHRlcihidWcgPT0gVFJVRSkKYGBgCgoKYGBge3J9CmZpbGVuYW1lIDwtICdkYXRhL2RvZy5zdGF0cy5jc3YnCmRvZ3Nfb3JnIDwtIHJlYWRfY3N2KGZpbGVuYW1lKQpgYGAKCmBgYHtyfQpmaWxlbmFtZSA8LSAnZGF0YS9jYXQuc3RhdHMuY3N2JwpjYXRzX29yZyA8LSByZWFkX2NzdihmaWxlbmFtZSkKYGBgCgojIyBDbGVhbiBEYXRhCgoKCmBgYHtyfQpwcmVwYXJlX2RhdGEgPC0gZnVuY3Rpb24gKGRhdGEpIHsKICBuZXdfZGF0YSA8LSBkYXRhICU+JSBtdXRhdGUoZHJhd2luZ190aW1lX3NlY29uZHMgPSBkcmF3aW5nX3RpbWUgLyAxMDAwLCBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzID0gZHJhd2luZ190aW1lX2RyYXcgLyAxMDAwLCBkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcyA9IGRyYXdpbmdfdGltZV9wYXVzZSAvIDEwMDApCiAgCiAgbmV3X2RhdGEgPC0gbmV3X2RhdGEgJT4lIAogICAgIyBhIGZldyBoYXZlIHRpbWUgdmFsdWVzIG5vdCBpbiBpbmNyZW1lbnRhbAogICAgZmlsdGVyKHN0cm9rZV9pbl9vcmRlciA9PSAwKSAlPiUgCiAgICAjIGEgZmV3IGhhdmUgd2VpcmQgdGltZXMKICAgIGZpbHRlcihkcmF3aW5nX3RpbWVfbWluID49IDApICU+JSAKICAgIGZpbHRlcihkcmF3aW5nX3RpbWVfbWF4ID4gMCkgJT4lCiAgICBmaWx0ZXIoZHJhd2luZ190aW1lX2RyYXcgPiAxMDApCiAgcmV0dXJuKG5ld19kYXRhKQp9CmBgYAoKCmBgYHtyfQpkb2dzIDwtIHByZXBhcmVfZGF0YShkb2dzX29yZykKY2F0cyA8LSBwcmVwYXJlX2RhdGEoY2F0c19vcmcpCmBgYAoKCmBgYHtyfQpkb2dzICU+JSBmaWx0ZXIocmVjb2duaXplZCA9PSAnVHJ1ZScpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKyAKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBEb2cgRHJhd2luZyBUaW1lIikKYGBgCgpgYGB7cn0KZG9ncyAlPiUgZmlsdGVyKHJlY29nbml6ZWQgPT0gJ1RydWUnKSAlPiUgIGZpbHRlcihkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzIDwgMjUpICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gIiM2MDdkOGIiKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgRG9nIERyYXdpbmcgVGltZSIpCmBgYAoKCmBgYHtyfQpkb2dzICU+JSBmaWx0ZXIocmVjb2duaXplZCA9PSAnVHJ1ZScpICU+JSAgZmlsdGVyKGRyYXdpbmdfdGltZV9zZWNvbmRzIDwgMjUpICU+JSAgI2ZpbHRlcihzdHJva2VfY291bnQgPCA0KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfc2Vjb25kcywgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBmaWxsID0gIiM2MDdkOGIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsMjApKSArCiAgbGFicyh0aXRsZSA9ICJEb2cgVG90YWwgRHJhd2luZyBUaW1lIiwgeSA9ICIiLCB4ID0gIiIpICsKICB0aGVtZV9qb3koKQoKZ2dzYXZlKCJkb2dfdG90YWwucG5nIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA1KQpgYGAKCmBgYHtyfQpkb2dzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzLCBmaWxsID0gcmVjb2duaXplZCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsgCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgRG9nIERyYXdpbmcgVGltZSIpCmBgYAoKCmBgYHtyfQpjYXRzICU+JSBmaWx0ZXIocmVjb2duaXplZCA9PSAnVHJ1ZScpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKyAKICBsYWJzKHRpdGxlID0gIkhpc3RvZ3JhbSBvZiBDYXQgRHJhd2luZyBUaW1lIikKYGBgCgpgYGB7cn0KZG9nc19jYXRzIDwtIHJiaW5kKGRvZ3MsIGNhdHMpCmBgYAoKYGBge3J9CmRvZ3NfY2F0cyAlPiUgZmlsdGVyKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMgPD0gMjApICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMsIHkgPSB3b3JkKSkrCiAgZ2VvbV9qb3koc2NhbGUgPSA0KSArIHRoZW1lX2pveSgpICsKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMC4wMSwgMCkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkKYGBgCgoKYGBge3J9CmRvZ3NfY2F0c19yZWNfc3VtIDwtIGRvZ3NfY2F0cyAlPiUgZ3JvdXBfYnkod29yZCwgcmVjb2duaXplZCkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIG11dGF0ZShmcmVxID0gY291bnQgLyBzdW0oY291bnQpKQpgYGAKCgpgYGB7cn0KZG9nc19jYXRzX3JlY19zdW0gJT4lCiAgZ2dwbG90KGFlcyh4ID0gd29yZCwgeSA9IGZyZXEsIGZpbGwgPSByZWNvZ25pemVkKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKQpgYGAKCgoKYGBge3J9CmNhdHNfcmVjIDwtIGNhdHMgJT4lIGZpbHRlcihyZWNvZ25pemVkID09ICdUcnVlJykKZG9nc19yZWMgPC0gZG9ncyAlPiUgZmlsdGVyKHJlY29nbml6ZWQgPT0gJ1RydWUnKQpgYGAKCmBgYHtyfQpkb2dzX2NhdHNfcmVjIDwtIHJiaW5kKGRvZ3NfcmVjLCBjYXRzX3JlYykKYGBgCgpgYGB7cn0KZG9nc19jYXRzX3JlYyAlPiUKICBnZ3Bsb3QoYWVzKHggPSB3b3JkLCB5ID0gZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMpKSArCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgpgYGB7cn0Kc3VtbWFyeShkb2dzX3JlYyRkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcykKc3VtbWFyeShjYXRzX3JlYyRkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcykKYGBgCgoKYGBge3J9CiNkb2dzX2NhdHMgPC0gcmJpbmQoY2F0X2RyYXdpbmdzX3JlYywgZG9nX2RyYXdpbmdzX3JlYykKYGBgCgoKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gY2F0c19yZWMsIGFlcyh4ID0gZHJhd2luZ190aW1lX3NlY29uZHMsIHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGFscGhhID0gMC42LCBmaWxsID0gJ3JlZCcsIGJpbndpZHRoID0gMSkgKwogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBkb2dzX3JlYywgYWVzKHggPSBkcmF3aW5nX3RpbWVfc2Vjb25kcywgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSwgYWxwaGEgPSAwLjYsIGZpbGwgPSAnYmx1ZScsIGJpbndpZHRoID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDMwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgVG90YWwgU2Vjb25kcyBUYWtlbiBmb3IgRHJhd2luZyBhIGNhdCB2cyBhIGRvZyIsIHkgPSAiIiwgeCA9ICJEcmF3aW5nIFRpbWUgKHNlYykiKQogIApgYGAKCgpgYGB7cn0KZG9nc19jYXRzICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3NlY29uZHMgPiAyMCkgJT4lIGNvdW50KCkKZG9nc19jYXRzICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3NlY29uZHMgPiAyMCkgJT4lIGNvdW50KCkgLyBucm93KGRvZ3NfY2F0cykKYGBgCgpgYGB7cn0Kc3VtbWFyeShkb2dzX3JlYyRkcmF3aW5nX3RpbWVfc2Vjb25kcykKc3VtbWFyeShjYXRzX3JlYyRkcmF3aW5nX3RpbWVfc2Vjb25kcykKYGBgCgoKYGBge3J9CmRvZ3NfY2F0cyAlPiUgZmlsdGVyKGRyYXdpbmdfdGltZV9zZWNvbmRzID4gMjApICU+JQogIGdncGxvdChhZXMoeCA9IHdvcmQsIHkgPSBkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcykpICsgCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgoKYGBge3J9CmdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gY2F0c19yZWMsIGFlcyh4ID0gZHJhd2luZ190aW1lX3NlY29uZHMsIHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGFscGhhID0gMC42LCBmaWxsID0gJ3JlZCcsIGJpbndpZHRoID0gMSkgKwogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBkb2dzX3JlYywgYWVzKHggPSBkcmF3aW5nX3RpbWVfc2Vjb25kcywgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSwgYWxwaGEgPSAwLjYsIGZpbGwgPSAnYmx1ZScsIGJpbndpZHRoID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDI1KSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgVG90YWwgU2Vjb25kcyBUYWtlbiBmb3IgRHJhd2luZyBhIGNhdCB2cyBhIGRvZyIsIHkgPSAiIiwgeCA9ICJEcmF3aW5nIFRpbWUgKHNlYykiKQogIApgYGAKCmBgYHtyfQogcDwtIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gY2F0c19yZWMsIGFlcyh4ID0gZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcywgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSwgYWxwaGEgPSAwLjYsIGZpbGwgPSAncmVkJywgYmlud2lkdGggPSAxLCBjZW50ZXIgPSAwLCBjbG9zZWQgPSAnbGVmdCcpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gZG9nc19yZWMsIGFlcyh4ID0gZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcywgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSwgYWxwaGEgPSAwLjYsIGZpbGwgPSAnYmx1ZScsIGJpbndpZHRoID0gMSwgY2VudGVyID0gMCwgY2xvc2VkID0gJ2xlZnQnKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjUpLCBicmVha3MgPSBjKDAsMSwyLDMsNCw1LDYsNyw4LDksMTApKSArIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBEcmF3aW5nIFNlY29uZHMgVGFrZW4gZm9yIERyYXdpbmcgYSBjYXQgdnMgYSBkb2ciLCB5ID0gIiIsIHggPSAiRHJhd2luZyBUaW1lIChzZWMpIikKcGcgPC0gZ2dwbG90X2J1aWxkKHApCnBnCmBgYAoKCmBgYHtyfQpkb2dzX3JlYyA8LSBkb2dzX3JlYyAlPiUgbXV0YXRlKHRpbWVfYmluID0gZmxvb3IoZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcykpCmRvZ19iaW5zIDwtIGRvZ3NfcmVjICU+JSBncm91cF9ieSh0aW1lX2JpbikgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIG11dGF0ZSggZnJlcSA9IGNvdW50IC8gc3VtKGNvdW50KSkKYGBgCgpgYGB7cn0KY2F0c19yZWMgPC0gY2F0c19yZWMgJT4lIG11dGF0ZSh0aW1lX2JpbiA9IGZsb29yKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpKQpjYXRfYmlucyA8LSBjYXRzX3JlYyAlPiUgZ3JvdXBfYnkodGltZV9iaW4pICU+JSBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSBtdXRhdGUoIGZyZXEgPSBjb3VudCAvIHN1bShjb3VudCkpCmBgYAoKYGBge3J9CmRvZ19iaW5zICU+JQogIGdncGxvdCgpICsgCiAgZ2VvbV9iYXIoZGF0YSA9IGRvZ19iaW5zLCBtYXBwaW5nID0gYWVzKHggPSB0aW1lX2JpbiwgeSA9IGZyZXEpLCBzdGF0PSdpZGVudGl0eScsIGZpbGwgPSAnYmx1ZScsIGFscGhhID0gMC42KSArIAogIGdlb21fYmFyKGRhdGEgPSBjYXRfYmlucywgbWFwcGluZyA9IGFlcyh4ID0gdGltZV9iaW4sIHkgPSBmcmVxKSwgc3RhdD0naWRlbnRpdHknLCBmaWxsID0gJ3JlZCcsIGFscGhhID0gMC42KSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygwLCAyNSkpCmBgYAoKCiMjIFNhbXBsZSBEYXRhCgpUZXN0IGlmIHRoZSBkaWZmZXJlbnQgbiBzaXplcyBhZmZlY3RpbmcgZGF0YS4KCmBgYHtyfQpjYXRzX3JlY19zYW1wbGUgPC0gY2F0c19yZWMgJT4lIHNhbXBsZV9uKDUwMDAwKQpkb2dzX3JlY19zYW1wbGUgPC0gZG9nc19yZWMgJT4lIHNhbXBsZV9uKDUwMDAwKQpgYGAKCgpgYGB7cn0KICBnZ3Bsb3QoKSArCiAgZ2VvbV9oaXN0b2dyYW0oZGF0YSA9IGNhdHNfcmVjX3NhbXBsZSwgYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzLCB5ID0gKC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCBhbHBoYSA9IDAuNiwgZmlsbCA9ICdyZWQnLCBiaW53aWR0aCA9IDEpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gZG9nc19yZWNfc2FtcGxlLCBhZXMoeCA9IGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMsIHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGFscGhhID0gMC42LCBmaWxsID0gJ2JsdWUnLCBiaW53aWR0aCA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyNSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIERyYXdpbmcgU2Vjb25kcyBUYWtlbiBmb3IgRHJhd2luZyBhIGNhdCB2cyBhIGRvZyIsIHkgPSAiIiwgeCA9ICJEcmF3aW5nIFRpbWUgKHNlYykiKQpgYGAKCiMjIFBhdXNlIFRpbWUKCmBgYHtyfQogIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gY2F0c19yZWMsIGFlcyh4ID0gZHJhd2luZ190aW1lX3BhdXNlIC8gMTAwMCwgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSwgYWxwaGEgPSAwLjYsIGZpbGwgPSAncmVkJywgYmlud2lkdGggPSAxKSArCiAgZ2VvbV9oaXN0b2dyYW0oZGF0YSA9IGRvZ3NfcmVjLCBhZXMoeCA9IGRyYXdpbmdfdGltZV9wYXVzZSAvIDEwMDAsIHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIGFscGhhID0gMC42LCBmaWxsID0gJ2JsdWUnLCBiaW53aWR0aCA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyNSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFBhdXNlIFNlY29uZHMgVGFrZW4gZm9yIERyYXdpbmcgYSBjYXQgdnMgYSBkb2ciLCB5ID0gIiIsIHggPSAiRHJhd2luZyBUaW1lIChzZWMpIikKYGBgCgoKCmBgYHtyfQptZWFuKGNhdHNfcmVjJGRyYXdpbmdfdGltZV9zZWNvbmRzKQptZWFuKGRvZ3NfcmVjJGRyYXdpbmdfdGltZV9zZWNvbmRzKQpgYGAKCgpgYGB7cn0KbWVhbihjYXRzX3JlYyRkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzKQptZWFuKGRvZ3NfcmVjJGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpCmBgYAoKCmBgYHtyfQptZWFuKGNhdHNfcmVjJHN0cm9rZV9jb3VudCkKbWVhbihkb2dzX3JlYyRzdHJva2VfY291bnQpCmBgYAoKYGBge3J9CmRvZ3NfcmVjICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcyA8IDMwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzLCB5ID0gc3Ryb2tlX2NvdW50KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAxIC8gMTAwKQogIApgYGAKCmBgYHtyfQpjYXRzX3JlYyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzLCB5ID0gc3Ryb2tlX2NvdW50KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAxIC8gMTApCiAgCmBgYAoKYGBge3J9CmNhdHNfcmVjICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMgPCAyMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMsIHkgPSBzdHJva2VfY291bnQpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAxIC8gMTApICsKICBnZW9tX3Ntb290aChtZXRob2Q9J2xtJykKYGBgCgpgYGB7cn0KY2F0c19yZWNfZmlsdGVyZWQgPC0gY2F0c19yZWMgJT4lIGZpbHRlcihkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcyA8IDIwKQoKYGBgCgpgYGB7cn0KZml0IDwtIGxtKGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzIH4gc3Ryb2tlX2NvdW50ICwgZGF0YSA9IGNhdHNfcmVjX2ZpbHRlcmVkKQpzdW1tYXJ5KGZpdCkKYGBgCgoKCmBgYHtyfQpjb3VudHJ5Y29kZXNfZG9ncyA8LSBkb2dzX3JlYyAlPiUgZ3JvdXBfYnkoY291bnRyeWNvZGUpICU+JSBzdW1tYXJpc2UoY291bnRyeV9jb3VudCA9IG4oKSkgJT4lIGFycmFuZ2UoLWNvdW50cnlfY291bnQpCmNvdW50cnljb2Rlc19jYXRzIDwtIGNhdHNfcmVjICU+JSBncm91cF9ieShjb3VudHJ5Y29kZSkgJT4lIHN1bW1hcmlzZShjb3VudHJ5X2NvdW50ID0gbigpKSAlPiUgYXJyYW5nZSgtY291bnRyeV9jb3VudCkKYGBgCgpgYGB7cn0KdG9wX2NvdW50cnljb2RlcyA8LSBjb3VudHJ5Y29kZXNfZG9ncyAlPiUgaGVhZChuID0gMzApCmBgYAoKYGBge3J9CmRvZ3NfcmVjX3RvcF9jb3VudHJpZXMgPC0gZG9nc19yZWMgJT4lIGZpbHRlcihjb3VudHJ5Y29kZSAlaW4lIHRvcF9jb3VudHJ5Y29kZXMkY291bnRyeWNvZGUpCgpkb2dzX3JlY190b3BfY291bnRyaWVzIDwtIGRvZ3NfcmVjX3RvcF9jb3VudHJpZXMgJT4lIGxlZnRfam9pbih0b3BfY291bnRyeWNvZGVzLCBieSA9ICJjb3VudHJ5Y29kZSIpCmBgYAoKYGBge3J9CmRvZ3NfcmVjX3RvcF9jb3VudHJpZXMgJT4lIGZpbHRlcihkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzIDwgMzApICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpKSArCiAgZmFjZXRfd3JhcCh+IGNvdW50cnljb2RlKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9KC4uY291bnQuLikvdGFwcGx5KC4uY291bnQuLiwuLlBBTkVMLi4sc3VtKVsuLlBBTkVMLi5dKSwgYmlud2lkdGggPSAxKSAKYGBgCgpgYGB7cn0KZG9nc19yZWNfdG9wX2NvdW50cmllcyAlPiUgZmlsdGVyKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMgPCAzMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcykpICsKICBmYWNldF93cmFwKH4gY291bnRyeWNvZGUpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeT0oLi5jb3VudC4uKS90YXBwbHkoLi5jb3VudC4uLC4uUEFORUwuLixzdW0pWy4uUEFORUwuLl0pLCBiaW53aWR0aCA9IDEpIAogIApgYGAKCgpgYGB7cn0KZG9nc19yZWNfdG9wX2NvdW50cmllcyAlPiUgZmlsdGVyKGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzIDwgMTUpICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzKSkgKwogIGZhY2V0X3dyYXAofiBjb3VudHJ5Y29kZSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5PSguLmNvdW50Li4pL3RhcHBseSguLmNvdW50Li4sLi5QQU5FTC4uLHN1bSlbLi5QQU5FTC4uXSksIGJpbndpZHRoID0gMSkgCiAgCmBgYAoKCiMgQ2F0ZWdvcnkgc3ViLXNlY3Rpb25zCgpgYGB7cn0KcmVhZF9uYW1lcyA8LSBmdW5jdGlvbiAobmFtZXMpIHsKICBkYXRhX3BhdGggPC0gJy4vZGF0YS8nCiAgYWxsX2NhdGVzIDwtIHZlY3RvcigibGlzdCIsIG5yb3cobmFtZXMpKSAgCiAgCiAgZm9yKGkgaW4gMTpucm93KG5hbWVzKSkgewogICAgbmFtZV9maWxlIDwtIG5hbWVzW2ksICJiYXNlbmFtZSJdCiAgICBmdWxsX3BhdGggPC0gcGFzdGUoZGF0YV9wYXRoLCBuYW1lX2ZpbGUsICIuc3RhdHMuY3N2Iiwgc2VwPScnKQogICAgbmFtZSA8LSByZWFkX2NzdihmdWxsX3BhdGgpCiAgICBhbGxfY2F0ZXNbW2ldXSA8LSBuYW1lCiAgfQogIAogIGFsbF9jYXRlc19kZiA8LSBkby5jYWxsKCJyYmluZCIsIGFsbF9jYXRlcykKICAKICBhbGxfY2F0ZXNfZGZfY2xlYW4gPC0gcHJlcGFyZV9kYXRhKGFsbF9jYXRlc19kZikKCiAgYWxsX2NhdGVzX2RmX2NsZWFuX3JlYyA8LSBhbGxfY2F0ZXNfZGZfY2xlYW4gJT4lIGZpbHRlcihyZWNvZ25pemVkID09ICdUcnVlJykKICAKICByZXR1cm4oYWxsX2NhdGVzX2RmX2NsZWFuX3JlYykKICAKfQpgYGAKCmBgYHtyfQphbGxfYnVnc19kZiA8LSByZWFkX25hbWVzKGJ1Z3MpCmBgYAoKYGBge3J9CmJ1Z3NfYWdnIDwtIGFsbF9idWdzX2RmICU+JSBncm91cF9ieSh3b3JkKSAlPiUgc3VtbWFyaXNlKGNvdW50ID0gbigpLAogICAgICAgICAgICBzdHJva2VfY291bnRfbWVhbiA9IG1lYW4oc3Ryb2tlX2NvdW50KSwKICAgICAgICAgICAgc3Ryb2tlX2NvdW50X21lZCA9IG1lZGlhbihzdHJva2VfY291bnQpLAogICAgICAgICAgICBkcmF3aW5nX3RpbWVfcGF1c2Vfc2VjX21lYW4gPSBtZWFuKGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzKSwgCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9wYXVzZV9zZWNfbWVkID0gbWVkaWFuKGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzKSwgCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9kcmF3X3NlY19tZWFuID0gbWVhbihkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzKSwgCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9kcmF3X3NlY19tZWQgPSBtZWRpYW4oZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcykpICU+JQogIGFycmFuZ2UoLWRyYXdpbmdfdGltZV9kcmF3X3NlY19tZWFuKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9NH0KYWxsX2J1Z3NfZGYgJT4lIApnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzLCB5ID0gZmFjdG9yKHdvcmQsIGxldmVscyA9IGJ1Z3NfYWdnJHdvcmQpLCBmaWxsID0gZmFjdG9yKHdvcmQsIGxldmVscyA9IGJ1Z3NfYWdnJHdvcmQpKSkgKwpnZW9tX2pveShzaXplID0gMC41NSApICsKICB0aGVtZV9qb3koKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDEsIDIwKSwgZXhwYW5kID0gYygwLjAxLCAwKSkgKwogIHNjYWxlX3lfZGlzY3JldGUoZXhwYW5kID0gYygwLjAxLCAwKSkgKyAKICBzY2FsZV9maWxsX2JyZXdlcihndWlkZSA9IEZBTFNFLCBwYWxldHRlID0gIkdyZXlzIiwgZGlyZWN0aW9uID0gLTEpICsgCiAgbGFicyh0aXRsZSA9ICdCdWdzJywgeCA9ICcnLCB5ID0gJycpCmdnc2F2ZSgnYnVncy5wbmcnLCB3aWR0aCA9IDgsIGhlaWdodCA9IDEyKQpgYGAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpmcnVpdHMgPC0gbWV0YSAlPiUgZmlsdGVyKGZydWl0ID09IFRSVUUpCmFsbF9mcnVpdHMgPC0gcmVhZF9uYW1lcyhmcnVpdHMpCmBgYAoKYGBge3J9CmZydWl0c19hZ2cgPC0gYWxsX2ZydWl0cyAlPiUgZ3JvdXBfYnkod29yZCkgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSwKICAgICAgICAgICAgc3Ryb2tlX2NvdW50X21lYW4gPSBtZWFuKHN0cm9rZV9jb3VudCksCiAgICAgICAgICAgIHN0cm9rZV9jb3VudF9tZWQgPSBtZWRpYW4oc3Ryb2tlX2NvdW50KSwKICAgICAgICAgICAgZHJhd2luZ190aW1lX3BhdXNlX3NlY19tZWFuID0gbWVhbihkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcyksIAogICAgICAgICAgICBkcmF3aW5nX3RpbWVfcGF1c2Vfc2VjX21lZCA9IG1lZGlhbihkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcyksIAogICAgICAgICAgICBkcmF3aW5nX3RpbWVfZHJhd19zZWNfbWVhbiA9IG1lYW4oZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcyksIAogICAgICAgICAgICBkcmF3aW5nX3RpbWVfZHJhd19zZWNfbWVkID0gbWVkaWFuKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpKSAlPiUKICBhcnJhbmdlKC1kcmF3aW5nX3RpbWVfZHJhd19zZWNfbWVhbikKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTR9CmFsbF9mcnVpdHMgJT4lIApnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzLCB5ID0gZmFjdG9yKHdvcmQsIGxldmVscyA9IGZydWl0c19hZ2ckd29yZCksIGZpbGwgPSBmYWN0b3Iod29yZCwgbGV2ZWxzID0gZnJ1aXRzX2FnZyR3b3JkKSkpICsKZ2VvbV9qb3koc2l6ZSA9IDAuNTUgKSArCiAgdGhlbWVfam95KCkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygxLCAyMCksIGV4cGFuZCA9IGMoMC4wMSwgMCkpICsKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMC4wMSwgMCkpICsgCiAgc2NhbGVfZmlsbF9icmV3ZXIoZ3VpZGUgPSBGQUxTRSwgcGFsZXR0ZSA9ICJPcmFuZ2VzIiwgZGlyZWN0aW9uID0gLTEpICsgCiAgbGFicyh0aXRsZSA9ICdGcnVpdHMnLCB4ID0gJycsIHkgPSAnJykKZ2dzYXZlKCdmcnVpdHMucG5nJywgd2lkdGggPSA4LCBoZWlnaHQgPSAxMikKYGBgCgpgYGB7cn0KYWxsX2ZydWl0cyAlPiUgZmlsdGVyKHdvcmQgPT0gImJhbmFuYSIpICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzLCAgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBmaWxsID0gIiNGRkQ2MDAiKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgdGhlbWVfam95KCkgICsgCiAgbGFicyh0aXRsZSA9ICJCYW5hbmEgVG90YWwgRHJhd2luZyBUaW1lIiwgeCA9ICIiLCB5ID0gIiIpCmdnc2F2ZSgiYmFuYW5hX3RvdGFsLnBuZyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSkKYGBgCgoKYGBge3J9CmFsbF9mcnVpdHMgJT4lIGZpbHRlcih3b3JkID09ICJiYW5hbmEiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMDApICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyMDAwMCkpCmBgYAoKYGBge3J9CmFsbF9mcnVpdHMgJT4lIGZpbHRlcih3b3JkID09ICJiYW5hbmEiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzdHJva2VfY291bnQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSAKICAjc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjApKQpgYGAKCmBgYHtyfQphbGxfZnJ1aXRzICU+JSBmaWx0ZXIoc3Ryb2tlX2NvdW50IDwgNSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTAwKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjAwMDApKQpgYGAKCgpgYGB7cn0KYWxsX2NhdGVzICU+JSAjZmlsdGVyKHN0cm9rZV9jb3VudCA8IDUpICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzLCAgeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMCkpICsgCiAgdGhlbWVfam95KCkgKwogIGxhYnModGl0bGUgPSAiQWxsIENhdGVnb3JpZXMgVG90YWwgRHJhd2luZyBUaW1lIChiaW53aWR0aCA9IDEpIiwgeSA9ICcnLCB4ID0gJycpCmdnc2F2ZSgnYWxsX3RvdGFsXzEucG5nJywgd2lkdGggPSA2LCBoZWlnaHQgPSA1KQpgYGAKCmBgYHtyfQpiYW5hbmFzIDwtIGFsbF9mcnVpdHMgJT4lIGZpbHRlcih3b3JkID09ICJiYW5hbmEiKQpgYGAKCgpgYGB7cn0KcGVhcnMgPC0gYWxsX2ZydWl0cyAlPiUgZmlsdGVyKHdvcmQgPT0gJ3BlYXInKQpgYGAKCmBgYHtyfQpiYW5hbmFzJHJvdW5kX3RpbWUgPC0gcm91bmQoYmFuYW5hcyRkcmF3aW5nX3RpbWVfc2Vjb25kcywgMSkKYGBgCgoKYGBge3J9CmJhbmFuYXMgJT4lIGZpbHRlcihyZWNvZ25pemVkID09ICdUcnVlJykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcyApKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjUsIDgpKQoKYGBgCgpgYGB7cn0KZ2dwbG90KCkgKwogIGdlb21faGlzdG9ncmFtKGRhdGEgPSBiYW5hbmFzLCBhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzLCB5ID0gKC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCBhbHBoYSA9IDEuMCwgZmlsbCA9ICIjRkZENjAwIiwgYmlud2lkdGggPSAwLjEpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gYWxsX2ZydWl0cyAlPiUgZmlsdGVyKHN0cm9rZV9jb3VudCA8IDUpLCBhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzLCB5ID0gKC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCBhbHBoYSA9IDAuNiwgZmlsbCA9ICdibGFjaycsIGJpbndpZHRoID0gMC4xKSArCiAgI2dlb21faGlzdG9ncmFtKGRhdGEgPSBkb2dzLCBhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzLCB5ID0gKC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCBhbHBoYSA9IDAuNiwgZmlsbCA9ICdibHVlJywgYmlud2lkdGggPSAwLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMCksIGJyZWFrcyA9IHNlcSgwLDEwLDAuNSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIGxhYnModGl0bGUgPSAiQmFuYW5hIHZzIEFsbCBGcnVpdCBEcmF3aW5nIFRpbWUgKGJpbndpZHRoID0gMC4xKSIsIHkgPSAiIiwgeCA9ICJEcmF3aW5nIFRpbWUgKHNlY3MpIikgKwogIHRoZW1lX2xpZ2h0KCkKZ2dzYXZlKCJiYW5hbmFzX3ZzX2ZydWl0LnBuZyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSkgCmBgYAoKYGBge3J9Cm1lYW4oYWxsX2ZydWl0cyRkcmF3aW5nX3RpbWVfc2Vjb25kcykKbWVhbihkb2dzJGRyYXdpbmdfdGltZV9zZWNvbmRzKQpgYGAKCgpgYGB7cn0KCmdldG1vZGUgPC0gZnVuY3Rpb24odikgewogICB1bmlxdiA8LSB1bmlxdWUodikKICAgdW5pcXZbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHYsIHVuaXF2KSkpXQp9CgoKZ2V0bW9kZShiYW5hbmFzJGRyYXdpbmdfdGltZV9zZWNvbmRzKQpgYGAKYGBge3J9CmJhbmFuYXNfdHdvX3NlYyA8LSBiYW5hbmFzICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3NlY29uZHMgPiAyLjUpICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3NlY29uZHMgPCAzLjApCmBgYAoKYGBge3J9CnN1bW1hcnkoKQpgYGAKCgpgYGB7cn0KYmFuYW5hc190d29fc2VjICU+JQogIGdncGxvdChhZXMoeCA9ICBmYWN0b3Ioc3Ryb2tlX2NvdW50KSkpICsKICBnZW9tX2JhcigpCmBgYAoKCgpgYGB7cn0KYmFuYW5hcyAlPiUgZmlsdGVyKHN0cm9rZV9jb3VudCA8IDQpICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMSwgOCkpICsgCiAgZmFjZXRfd3JhcCh+IHN0cm9rZV9jb3VudCkKYGBgCgpgYGB7cn0KcGVhcnMgJT4lIGZpbHRlcihzdHJva2VfY291bnQgPCA2KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfc2Vjb25kcykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwKSkgKyAKICBmYWNldF93cmFwKH4gc3Ryb2tlX2NvdW50KQpgYGAKCgpgYGB7cn0KZG9ncyAlPiUgZmlsdGVyKHN0cm9rZV9jb3VudCA8IDQpICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3NlY29uZHMgPCAyMCkgJT4lIGZpbHRlcihyZWNvZ25pemVkID09ICdUcnVlJykgICU+JQogIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9zZWNvbmRzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoNCwgMTEpKSArCiAgZmFjZXRfd3JhcCh+IHN0cm9rZV9jb3VudCkKYGBgCgpgYGB7cn0KZG9nc19tIDwtIGRvZ3MgJT4lIG11dGF0ZShzZWMgPSBmbG9vcihkcmF3aW5nX3RpbWVfc2Vjb25kcyksIHRpbWVfaW5fc2VjID0gZHJhd2luZ190aW1lX3NlY29uZHMgLSBzZWMpCmBgYAoKCmBgYHtyfQpkb2dzX20gJT4lIGZpbHRlcihzdHJva2VfY291bnQgPCA0KSAlPiUgZmlsdGVyKHNlYyAlaW4lIGMoNCw1LDYsNyw4LDksIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTUpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0aW1lX2luX3NlYykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDEpICsKICAjc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMSwgMjApKSArCiAgZmFjZXRfd3JhcCh+IHNlYykKYGBgCgpgYGB7cn0KZG9ncyAlPiUgZmlsdGVyKHN0cm9rZV9jb3VudCA8IDQpICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX3NlY29uZHMgPCAyMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lX3NlY29uZHMpKSArCiAgZ2VvbV9hcmVhKCkKYGBgCgoKYGBge3J9CmJhbmFuYXNfYnlfdGltZSA8LSBiYW5hbmFzICU+JSBncm91cF9ieShyb3VuZF90aW1lLCBzdHJva2VfY291bnQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIG11dGF0ZShmcmVxID0gbiAvIHN1bShuKSkKYGBgCgpgYGB7cn0KYmFuYW5hc19ieV90aW1lICU+JSBmaWx0ZXIocm91bmRfdGltZSA8IDIwKSAlPiUgZmlsdGVyKHN0cm9rZV9jb3VudCA8IDEwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByb3VuZF90aW1lLCBmaWxsID0gZmFjdG9yKHN0cm9rZV9jb3VudCksIHkgPSBmcmVxKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKQpgYGAKCgoKYGBge3IsIG1lc3NhZ2U9RkFMU0V9CmFuaW1hbHNfbWV0YSA8LSBtZXRhICU+JSBmaWx0ZXIoYW5pbWFsID09IFRSVUUpCmFsbF9hbmltYWxzIDwtIHJlYWRfbmFtZXMoYW5pbWFsc19tZXRhKQoKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmBgYAoKYGBge3J9CmFuaW1hbHNfYWdnIDwtIGFsbF9hbmltYWxzICU+JSBncm91cF9ieSh3b3JkKSAlPiUgc3VtbWFyaXNlKGNvdW50ID0gbigpLAogICAgICAgICAgICBzdHJva2VfY291bnRfbWVhbiA9IG1lYW4oc3Ryb2tlX2NvdW50KSwKICAgICAgICAgICAgc3Ryb2tlX2NvdW50X21lZCA9IG1lZGlhbihzdHJva2VfY291bnQpLAogICAgICAgICAgICBkcmF3aW5nX3RpbWVfcGF1c2Vfc2VjX21lYW4gPSBtZWFuKGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzKSwgCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9wYXVzZV9zZWNfbWVkID0gbWVkaWFuKGRyYXdpbmdfdGltZV9wYXVzZV9zZWNvbmRzKSwgCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9kcmF3X3NlY19tZWFuID0gbWVhbihkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzKSwgCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9kcmF3X3NlY19tZWQgPSBtZWRpYW4oZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcykpICU+JQogIGFycmFuZ2UoLWRyYXdpbmdfdGltZV9kcmF3X3NlY19tZWFuKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD00fQphbGxfYW5pbWFscyAlPiUgCmdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMsIHkgPSBmYWN0b3Iod29yZCwgbGV2ZWxzID0gYW5pbWFsc19hZ2ckd29yZCksIGZpbGwgPSBmYWN0b3Iod29yZCwgbGV2ZWxzID0gYW5pbWFsc19hZ2ckd29yZCkpKSArCmdlb21fam95KHNpemUgPSAwLjU1ICkgKwogIHRoZW1lX2pveSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMSwgMTgpLCBleHBhbmQgPSBjKDAuMDEsIDApKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAuMDEsIDApKSArIAogICNzY2FsZV9maWxsX2JyZXdlcihndWlkZSA9IEZBTFNFLCBwYWxldHRlID0gIllsR25CdSIsIGRpcmVjdGlvbiA9IC0xKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1yZXAoYnJld2VyLnBhbCg2LCJHbkJ1IiksdGltZXM9OSksIGd1aWRlID0gRkFMU0UpICsKICBsYWJzKHRpdGxlID0gJ0FuaW1hbHMnLCB4ID0gJycsIHkgPSAnJykKZ2dzYXZlKCdhbmltYWxzLnBuZycsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMTIpCmBgYAoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQphbGxfY2F0ZXMgPC0gcmVhZF9uYW1lcyhtZXRhKQpgYGAKCgpgYGB7cn0KYWxsX2FnZyA8LSBhbGxfY2F0ZXMgJT4lIGdyb3VwX2J5KHdvcmQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSwKICAgICAgICAgICAgc2NvdW50X21lID0gbWVhbihzdHJva2VfY291bnQpLAogICAgICAgICAgICBzY291bnRfbWQgPSBtZWRpYW4oc3Ryb2tlX2NvdW50KSwKICAgICAgICAgICAgZF9wYXVzZV9tZSA9IG1lYW4oZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMpLCAKICAgICAgICAgICAgZF9wYXVzZV9tZCA9IG1lZGlhbihkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcyksIAogICAgICAgICAgICBkX2RyYXdfbWUgPSBtZWFuKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpLCAKICAgICAgICAgICAgZF9kcmF3X21kID0gbWVkaWFuKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpLAogICAgICAgICAgICBkX3RvdGFsX21kID0gbWVkaWFuKGRyYXdpbmdfdGltZV9zZWNvbmRzKSwKICAgICAgICAgICAgZF90b3RhbF9tZSA9IG1lYW4oZHJhd2luZ190aW1lX3NlY29uZHMpKSAlPiUKICBhcnJhbmdlKC1kX2RyYXdfbWUpCmBgYAoKCmBgYHtyfQphbGxfYWdnX3JlYyA8LSBhbGxfY2F0ZXMgJT4lIGZpbHRlcihyZWNvZ25pemVkID09ICdUcnVlJykgJT4lIGdyb3VwX2J5KHdvcmQpICU+JSBzdW1tYXJpc2UobiA9IG4oKSwKICAgICAgICAgICAgc2NvdW50X21lID0gbWVhbihzdHJva2VfY291bnQpLAogICAgICAgICAgICBzY291bnRfbWQgPSBtZWRpYW4oc3Ryb2tlX2NvdW50KSwKICAgICAgICAgICAgZF9wYXVzZV9tZSA9IG1lYW4oZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMpLCAKICAgICAgICAgICAgZF9wYXVzZV9tZCA9IG1lZGlhbihkcmF3aW5nX3RpbWVfcGF1c2Vfc2Vjb25kcyksIAogICAgICAgICAgICBkX2RyYXdfbWUgPSBtZWFuKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpLCAKICAgICAgICAgICAgZF9kcmF3X21kID0gbWVkaWFuKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpLAogICAgICAgICAgICBkX3RvdGFsX21kID0gbWVkaWFuKGRyYXdpbmdfdGltZV9zZWNvbmRzKSwKICAgICAgICAgICAgZF90b3RhbF9tZSA9IG1lYW4oZHJhd2luZ190aW1lX3NlY29uZHMpKSAlPiUKICBhcnJhbmdlKC1kX2RyYXdfbWUpCmBgYAoKYGBge3J9CmFsbF9hZ2cgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lX2RyYXdfc2VjX21lYW4sIHkgPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNfbWVkKSkgKwogIGdlb21fcG9pbnQoKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdnYmVlc3dhcm0pCmBgYAoKCmBgYHtyfQphbGxfYWdnICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkcmF3aW5nX3RpbWVfZHJhd19zZWNfbWVkLCB5ID0gJycpKSArIAogIGdlb21fYmVlc3dhcm0oZ3JvdXBPblggPSBGQUxTRSwgY2V4PTIuOCwgc2l6ZSA9IDIpICsKICBsYWJzKHggPSAnJywgeSA9ICcnKQogICNnZW9tX3F1YXNpcmFuZG9tKGdyb3VwT25YID0gRkFMU0UsIHZhcndpZHRoID0gVFJVRSkKICAKYGBgCgpgYGB7cn0Kd3JpdGVfY3N2KGFsbF9hZ2csICdhbGxfYWdncmVnYXRlcy5jc3YnKQpgYGAKCgojIEFsbCBDYXRlZ29yaWVzCgpgYGB7cn0KZGF0YV9wYXRoIDwtICcuL2RhdGEvJwpzdGF0X2ZpbGVzIDwtIGxpc3QuZmlsZXMocGF0aCA9IGRhdGFfcGF0aCwgcGF0dGVybiA9ICdcXC5zdGF0c1xcLmNzdicpCmxlbmd0aChzdGF0X2ZpbGVzKQphbGxfY2F0ZXMgPC0gdmVjdG9yKCJsaXN0IixsZW5ndGgoc3RhdF9maWxlcykpCmxlbmd0aChhbGxfY2F0ZXMpCmBgYAoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmb3IoaSBpbiAxOmxlbmd0aChzdGF0X2ZpbGVzKSkgewogIHN0YXRfZmlsZSA8LSBzdGF0X2ZpbGVzW2ldCiAgZnVsbF9wYXRoIDwtIHBhc3RlKGRhdGFfcGF0aCwgc3RhdF9maWxlLCBzZXA9JycpCiAgcHJpbnQoZnVsbF9wYXRoKQogIGNhdGVfb3JnIDwtIHJlYWRfY3N2KGZ1bGxfcGF0aCkKICBjYXRlIDwtIHByZXBhcmVfZGF0YShjYXRlX29yZykKICBhbGxfY2F0ZXNbW2ldXSA8LSBjYXRlCiAgCn0KYGBgCgoKYGBge3J9CmFsbF9jYXRlc19kZiA8LSBkby5jYWxsKCJyYmluZCIsIGFsbF9jYXRlcykKYGBgCgpgYGB7cn0KYWxsX2NhdGVzX2RmX2NsZWFuIDwtIHByZXBhcmVfZGF0YShhbGxfY2F0ZXNfZGYpCmBgYAoKCmBgYHtyfQphbGxfY2F0ZXNfZGZfY2xlYW5fcmVjIDwtIGFsbF9jYXRlc19kZl9jbGVhbiAlPiUgZmlsdGVyKHJlY29nbml6ZWQgPT0gJ1RydWUnKQpgYGAKCgoKYGBge3J9CmFsbF9jYXRlc19tZWFuIDwtIGFsbF9jYXRlc19kZl9jbGVhbl9yZWMgJT4lIGdyb3VwX2J5KHdvcmQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksCiAgICAgICAgICAgIHN0cm9rZV9jb3VudF9tZWFuID0gbWVhbihzdHJva2VfY291bnQpLAogICAgICAgICAgICBzdHJva2VfY291bnRfbWVkID0gbWVkaWFuKHN0cm9rZV9jb3VudCksCiAgICAgICAgICAgIGRyYXdpbmdfdGltZV9wYXVzZV9zZWNfbWVhbiA9IG1lYW4oZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMpLCAKICAgICAgICAgICAgZHJhd2luZ190aW1lX3BhdXNlX3NlY19tZWQgPSBtZWRpYW4oZHJhd2luZ190aW1lX3BhdXNlX3NlY29uZHMpLCAKICAgICAgICAgICAgZHJhd2luZ190aW1lX2RyYXdfc2VjX21lYW4gPSBtZWFuKGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpLCAKICAgICAgICAgICAgZHJhd2luZ190aW1lX2RyYXdfc2VjX21lZCA9IG1lZGlhbihkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzKSkgJT4lCiAgYXJyYW5nZSgtZHJhd2luZ190aW1lX2RyYXdfc2VjX21lYW4pCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD00fQoKYWxsX2NhdGVzX2RmX2NsZWFuX3JlYyR3b3JkIDwtIGZhY3RvcihhbGxfY2F0ZXNfZGZfY2xlYW5fcmVjJHdvcmQsIGxldmVscyA9IGFsbF9jYXRlc19kZl9jbGVhbl9yZWMkd29yZFtvcmRlcihhbGxfY2F0ZXNfZGZfY2xlYW5fcmVjJHdvcmQpXSkKCgphbGxfY2F0ZXNfZGZfY2xlYW5fcmVjICU+JSBmaWx0ZXIoZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcyA8PSAyMCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZHJhd2luZ190aW1lX2RyYXdfc2Vjb25kcywgeSA9IHdvcmQgKSkrCiAgZ2VvbV9qb3koc2NhbGUgPSA0KSArIHRoZW1lX2pveSgpCmBgYAoKCmBgYHtyfQphbGxfY2F0ZXNfZGYgJT4lIGZpbHRlcih3b3JkID09ICdkb2cnKSAlPiUgY291bnQoKQpgYGAKCgoKCmBgYHtyfQphbGxfY2F0ZXNfZGZfY2xlYW5fcmVjICU+JSBmaWx0ZXIod29yZCA9PSAnZG9nJykgJT4lIGZpbHRlcihkcmF3aW5nX3RpbWVfZHJhd19zZWNvbmRzIDw9IDIwKSAlPiUKIGdncGxvdChhZXMoeCA9IGRyYXdpbmdfdGltZV9kcmF3X3NlY29uZHMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArIAogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIERyYXdpbmcgVGltZSIpCmBgYAoK